package cn.atcoder.air.transport;

import cn.atcoder.air.msg.RequestMessage;
import cn.atcoder.air.msg.ResponseMessage;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.nio.NioEventLoopGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author yangjunda1
 * @description todo
 * @date 2019/1/25 10:13
 */
public abstract class AbstractClientTransport implements ClientTransport {

    protected static final Logger LOGGER = LoggerFactory.getLogger(ClientTransport.class);

    public AbstractClientTransport(String host, int port) {
        this.host = host;
        this.port = port;
        shakeHandLock = new ReentrantLock();
    }

    protected String host;

    protected int port;

    protected NioEventLoopGroup workGroup = new NioEventLoopGroup(4);

    protected Channel channel;

    protected Bootstrap bootstrap;

    protected AtomicLong currentRequests = new AtomicLong(0);

    protected AtomicLong heartbeatTimes = new AtomicLong(0);

    protected AtomicBoolean shakeHanded = new AtomicBoolean();

    protected Lock shakeHandLock;

    protected Condition condition;

    protected String clientId;

    protected abstract ResponseMessage send(RequestMessage requestMessage, int timeout);

    abstract void start0();

    @Override
    public void start() {
        start0();

    }

    @Override
    public ResponseMessage send0(RequestMessage requestMessage, int timeout) {
        currentRequests.incrementAndGet();
        return send(requestMessage, timeout);
    }

    @Override
    public long currentRequests() {
        return currentRequests.get();
    }

    public void shakeHandedSuccess() {
        shakeHanded.set(Boolean.TRUE);
    }

    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    public boolean tryHeartbeat() {
        return heartbeatTimes.incrementAndGet() <= 30;
    }

    public void heartbeatSuccess() {
        heartbeatTimes.set(0);
        return;
    }
}
